package com.tebiecloud.mpopen.server.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.tebiecloud.common.utils.JsonUtils;
import com.tebiecloud.common.utils.RedisUtils;
import com.tebiecloud.common.utils.StringUtils;
import com.tebiecloud.mpopen.client.constants.MpopenConstants;
import com.tebiecloud.mpopen.client.model.entity.MpopenAuthorizationInfo;
import com.tebiecloud.mpopen.client.model.entity.MpopenAuthorizerInfo;
import com.tebiecloud.mpopen.client.model.mpopen.AccessToken;
import com.tebiecloud.mpopen.client.model.mpopen.ApiQueryAuth;
import com.tebiecloud.mpopen.client.model.mpopen.AuthorizerInfo;
import com.tebiecloud.mpopen.client.model.mpopen.PreAuthCode;
import com.tebiecloud.mpopen.server.properties.MpopenProperties;
import com.tebiecloud.mpopen.server.service.MpopenApiService;
import com.tebiecloud.mpopen.server.service.MpopenAuthorizationInfoService;
import com.tebiecloud.mpopen.server.service.MpopenAuthorizerInfoService;
import com.tebiecloud.mpopen.server.utils.MPSuiteApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * 第三方平台接口
 * @Author: tebie
 * @Date: 2019-09-09 20:19
 */
@Slf4j
@Service
public class MpopenApiServiceImpl implements MpopenApiService {

    @Autowired
    private MpopenProperties mpopenProperties;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private MpopenAuthorizationInfoService mpopenAuthorizationInfoService;

    @Autowired
    private MpopenAuthorizerInfoService mpopenAuthorizerInfoService;

    @Override
    public String getWxapiAccessToken(String appid, boolean force) {
        if(!force) {
            String access_token = redisUtils.get(MpopenConstants.MP_ACCESS_TOKEN_ + appid);
            if(StringUtils.isNotEmpty(access_token)) {
                return access_token;
            }
        }

        Object authorizer_refresh_tokenObj = redisUtils.hget(MpopenConstants.MP_AUTHORIZER_REFRESH_TOKEN, appid);
        String authorizer_refresh_token = authorizer_refresh_tokenObj != null ? authorizer_refresh_tokenObj.toString() : null;

        if(StringUtils.isEmpty(appid) || StringUtils.isEmpty(authorizer_refresh_token)) {
            log.error("xiaoc>> 获取微信公众号access_token失败, appid: {}, authorizer_refresh_token: {}", appid, authorizer_refresh_token);
            return null;
        }

        String mpsuite_appid = mpopenProperties.getAppid();
        String component_access_token = redisUtils.get(MpopenConstants.COMPONENT_ACCESS_TOKEN_ + mpsuite_appid);
        String data = String.format("{\"component_appid\":\"%s\",\"authorizer_appid\": \"%s\",\"authorizer_refresh_token\": \"%s\"}", mpsuite_appid, appid, authorizer_refresh_token);
        String response = MPSuiteApi.api_authorizer_token(component_access_token, data);

        JSONObject jsonObj = JsonUtils.str2Json(response);
        if(jsonObj != null && StringUtils.isNotEmpty(jsonObj.getString("authorizer_access_token"))) {
            String access_token = jsonObj.getString("authorizer_access_token");
            int expires_in = jsonObj.getIntValue("expires_in"); // 有效时间（秒）
            if(expires_in > 60) {
                redisUtils.set(MpopenConstants.MP_ACCESS_TOKEN_ + appid, access_token, expires_in - 60);
            }
            return access_token;
        }
        else {
            log.error("xiaoc>> 获取微信公众号access_token失败");
        }

        return null;
    }

    @Override
    public AccessToken getAccessToken(String appid, String code) {
        String mpsuite_appid = mpopenProperties.getAppid();
        String component_access_token = redisUtils.get(MpopenConstants.COMPONENT_ACCESS_TOKEN_ + mpsuite_appid);
        if(StringUtils.isEmpty(component_access_token)) {
            log.info("xioac>> 从redis获取第三方平台授权凭证component_access_token失败, mpsuite_appid: {}", mpsuite_appid);
            return null;
        }
        String resp = MPSuiteApi.access_token(appid, code, mpsuite_appid, component_access_token);
        return JsonUtils.str2Bean(resp, AccessToken.class);
    }

    @Override
    public ApiQueryAuth getApiQueryAuth(String authCode) {
        String mpsuite_appid = mpopenProperties.getAppid();
        String component_access_token = redisUtils.get(MpopenConstants.COMPONENT_ACCESS_TOKEN_ + mpsuite_appid);
        if(StringUtils.isEmpty(component_access_token)) {
            log.info("xioac>> 从redis获取第三方平台授权凭证component_access_token失败, mpsuite_appid: {}", mpsuite_appid);
            return null;
        }

        // 从微信获取数据
        String data = String.format("{\"component_appid\":\"%s\",\"authorization_code\": \"%s\"}", mpsuite_appid, authCode);
        String resp = MPSuiteApi.api_query_auth(component_access_token, data);
        JSONObject jsonApiQueryAuth = JsonUtils.str2Json(resp);
        if(jsonApiQueryAuth == null) {
            log.info("xiaoc>> 使用授权码换取公众号或小程序的接口调用凭据和授权信息失败, resp: {}", resp);
            return null;
        }

        // 获取授权信息
        ApiQueryAuth apiQueryAuth = JsonUtils.str2Bean(jsonApiQueryAuth.getString("authorization_info"), ApiQueryAuth.class);
        if(apiQueryAuth == null || StringUtils.isEmpty(apiQueryAuth.getAuthorizer_appid())) {
            log.info("xiaoc>> 使用授权码换取公众号或小程序的接口调用凭据和授权信息，数据转类对象失败, authorization_info: {}", jsonApiQueryAuth.getString("authorization_info"));
            return null;
        }

        // 更新缓存中授权信息
        redisUtils.hset(MpopenConstants.MP_AUTHORIZER_REFRESH_TOKEN, apiQueryAuth.getAuthorizer_appid(), apiQueryAuth.getAuthorizer_refresh_token());

        // 保存授权信息至数据库
        MpopenAuthorizationInfo mpopenAuthorizationInfo = new MpopenAuthorizationInfo();
        mpopenAuthorizationInfo.setAuthorizerAppid(apiQueryAuth.getAuthorizer_appid());
        mpopenAuthorizationInfo.setAuthorizerAccessToken(apiQueryAuth.getAuthorizer_access_token());
        mpopenAuthorizationInfo.setAuthorizerRefreshToken(apiQueryAuth.getAuthorizer_refresh_token());
        mpopenAuthorizationInfo.setExpiresIn(apiQueryAuth.getExpires_in());
        mpopenAuthorizationInfo.setFuncInfo(apiQueryAuth.getFunc_info());

        MpopenAuthorizationInfo mpopenAuthorizationInfoOld = mpopenAuthorizationInfoService.getLastOne(mpopenAuthorizationInfo.getAuthorizerAppid());
        if(mpopenAuthorizationInfoOld != null) {
            mpopenAuthorizationInfo.setAuthorizationInfoId(mpopenAuthorizationInfoOld.getAuthorizationInfoId());
            mpopenAuthorizationInfoService.updateById(mpopenAuthorizationInfo);
        } else {
            mpopenAuthorizationInfoService.save(mpopenAuthorizationInfo);
        }

        return apiQueryAuth;
    }

    @Override
    public AuthorizerInfo getAuthorizerInfo(String authorizerAppid) {
        String mpsuite_appid = mpopenProperties.getAppid();
        String component_access_token = redisUtils.get(MpopenConstants.COMPONENT_ACCESS_TOKEN_ + mpsuite_appid);
        if(StringUtils.isEmpty(component_access_token)) {
            log.info("xioac>> 从redis获取第三方平台授权凭证component_access_token失败, mpsuite_appid: {}", mpsuite_appid);
            return null;
        }

        // 从微信获取数据
        String data = String.format("{\"component_appid\":\"%s\" ,\"authorizer_appid\": \"%s\"}", mpsuite_appid, authorizerAppid);
        String resp = MPSuiteApi.api_get_authorizer_info(component_access_token, data);
        JSONObject jsonApiGetAuthorizerInfo = JsonUtils.str2Json(resp);
        if(jsonApiGetAuthorizerInfo == null) {
            log.info("xiaoc>> 获取授权方的帐号基本信息失败, resp: {}", resp);
            return null;
        }

        // 获取授权信息
        ApiQueryAuth apiQueryAuth = JsonUtils.str2Bean(jsonApiGetAuthorizerInfo.getString("authorization_info"), ApiQueryAuth.class);
        if(apiQueryAuth == null || StringUtils.isEmpty(apiQueryAuth.getAuthorizer_appid())) {
            log.info("xiaoc>> 使用授权码换取公众号或小程序的接口调用凭据和授权信息，数据转类对象失败, authorization_info: {}", jsonApiGetAuthorizerInfo.getString("authorization_info"));
            return null;
        }

//        // 更新缓存中授权信息
//        redisUtils.hset(MpopenConstants.MP_AUTHORIZER_REFRESH_TOKEN, apiQueryAuth.getAuthorizer_appid(), apiQueryAuth.getAuthorizer_refresh_token());
//
//        // 保存授权信息至数据库
//        MpopenAuthorizationInfo mpopenAuthorizationInfo = new MpopenAuthorizationInfo();
//        mpopenAuthorizationInfo.setAuthorizerAppid(apiQueryAuth.getAuthorizer_appid());
//        mpopenAuthorizationInfo.setAuthorizerAccessToken(apiQueryAuth.getAuthorizer_access_token());
//        mpopenAuthorizationInfo.setAuthorizerRefreshToken(apiQueryAuth.getAuthorizer_refresh_token());
//        mpopenAuthorizationInfo.setExpiresIn(apiQueryAuth.getExpires_in());
//        mpopenAuthorizationInfo.setFuncInfo(apiQueryAuth.getFunc_info());
//
//        MpopenAuthorizationInfo mpopenAuthorizationInfoOld = mpopenAuthorizationInfoService.getLastOne(mpopenAuthorizationInfo.getAuthorizerAppid());
//        if(mpopenAuthorizationInfoOld != null) {
//            mpopenAuthorizationInfo.setAuthorizationInfoId(mpopenAuthorizationInfoOld.getAuthorizationInfoId());
//            mpopenAuthorizationInfoService.updateById(mpopenAuthorizationInfo);
//        } else {
//            mpopenAuthorizationInfoService.save(mpopenAuthorizationInfo);
//        }

        // 获取公众号信息
        AuthorizerInfo authorizerInfo = JsonUtils.str2Bean(jsonApiGetAuthorizerInfo.getString("authorizer_info"), AuthorizerInfo.class);
        if(authorizerInfo == null || StringUtils.isEmpty(authorizerInfo.getUser_name())) {
            log.info("xiaoc>> 获取授权方的帐号基本信息，数据转类对象失败, authorizer_info: {}", jsonApiGetAuthorizerInfo.getString("authorizer_info"));
            return null;
        }

        // 保存公众号信息至数据库
        MpopenAuthorizerInfo mpopenAuthorizerInfo = new MpopenAuthorizerInfo();
        mpopenAuthorizerInfo.setNickName(authorizerInfo.getNick_name());
        mpopenAuthorizerInfo.setHeadImg(authorizerInfo.getHead_img());
        mpopenAuthorizerInfo.setServiceTypeInfo(JsonUtils.Obj2Str(authorizerInfo.getService_type_info()));
        mpopenAuthorizerInfo.setVerifyTypeinfo(JsonUtils.Obj2Str(authorizerInfo.getVerify_type_info()));
        mpopenAuthorizerInfo.setUserName(authorizerInfo.getUser_name());
        mpopenAuthorizerInfo.setPrincipalName(authorizerInfo.getPrincipal_name());
        mpopenAuthorizerInfo.setAlias(authorizerInfo.getAlias());
        mpopenAuthorizerInfo.setBusinessInfo(authorizerInfo.getBusiness_info());
        mpopenAuthorizerInfo.setQrcodeUrl(authorizerInfo.getQrcode_url());
        mpopenAuthorizerInfo.setAppId(apiQueryAuth.getAuthorizer_appid());
        mpopenAuthorizerInfo.setFuncInfo(apiQueryAuth.getFunc_info());
        mpopenAuthorizerInfoService.save(mpopenAuthorizerInfo);

        return authorizerInfo;
    }

    @Override
    public PreAuthCode getPreAuthCode() {
        String mpsuite_appid = mpopenProperties.getAppid();
        String component_access_token = redisUtils.get(MpopenConstants.COMPONENT_ACCESS_TOKEN_ + mpsuite_appid);
        if(StringUtils.isEmpty(component_access_token)) {
            log.info("xioac>> 从redis获取第三方平台授权凭证component_access_token失败, mpsuite_appid: {}", mpsuite_appid);
            return null;
        }

        String data = String.format("{\"component_appid\":\"%s\"}", mpsuite_appid);
        String resp = MPSuiteApi.component_access_token(component_access_token, data);
        return JsonUtils.str2Bean(resp, PreAuthCode.class);
    }
}
